// 启用严格模式，让 JavaScript 代码在更严格的语法规则下运行，有助于捕获常见编码错误。
'use strict'
// 引入 Node.js 的内置模块 path，用于处理和转换文件路径。
const path = require('path')

// 定义辅助函数 resolve，用于拼接当前文件所在目录和传入的路径。
// dir: 相对路径字符串，作为要拼接的路径部分。
// 返回值: 拼接后的绝对路径。
function resolve(dir) {
  // 使用 path.join 方法将当前文件所在目录 __dirname 和传入的路径 dir 拼接起来。
  return path.join(__dirname, dir)
}
// 引入 CompressionPlugin 插件，该插件用于在构建过程中对输出的文件进行 Gzip 压缩。
const CompressionPlugin = require('compression-webpack-plugin')
// 定义网页标题，优先从环境变量 VUE_APP_TITLE 中获取值，若环境变量未设置，则使用默认值 'RuoYi-Cloud-Plus管理系统'。
const name = process.env.VUE_APP_TITLE || 'RuoYi-Cloud-Plus管理系统' // 网页标题
// 定义开发服务器端口，优先从环境变量 port 或 npm_config_port 中获取值，若都未设置，则使用默认端口 80。
const port = process.env.port || process.env.npm_config_port || 80 // 端口

// 采用 CommonJS 模块规范，导出 Vue CLI 配置对象。
// 官方 vue.config.js 参考文档：https://cli.vuejs.org/zh/config/#css-loaderoptions
// 这里只列出部分配置，具体配置可参考官方文档。
module.exports = {
  // 部署生产环境和开发环境下应用的基础 URL。
  // 默认情况下，Vue CLI 假设应用部署在域名的根路径，如 https://www.ruoyi.vip/。
  // 若应用部署在子路径，如 https://www.ruoyi.vip/admin/，则需设置该值为 /admin/。
  // 这里从环境变量 VUE_APP_CONTEXT_PATH 中获取该值。
  publicPath: process.env.VUE_APP_CONTEXT_PATH,
  // 在执行 npm run build 或 yarn build 时，生成文件的目录名称。
  // 该目录名要和生产环境下的 publicPath 路径一致，默认值为 'dist'。
  outputDir: 'dist',
  // 用于存放生成的静态资源（如 js、css、img、fonts 等）的目录。
  // 项目打包后，静态资源会存放在该目录下。
  assetsDir: 'static',
  // 是否在保存文件时开启 ESLint 检测。
  // 当环境为开发环境（NODE_ENV 为 'development'）时开启检测，有效值为 true、false 或 'error'。
  lintOnSave: process.env.NODE_ENV === 'development',
  // 是否生成生产环境的 source map。
  // 若不需要生产环境的 source map，可设置为 false 以加快生产环境的构建速度。
  productionSourceMap: false,
  // webpack-dev-server 相关配置，用于开发环境下的服务器设置。
  devServer: {
    // 服务器监听的主机地址，'0.0.0.0' 表示监听所有网络接口。
    host: '0.0.0.0',
    // 使用前面定义的端口号。
    port: port,
    // 服务器启动后是否自动打开浏览器。
    open: true,
    // 配置 API 请求代理，用于解决开发环境下的跨域问题。
    proxy: {
      // 以环境变量 VUE_APP_BASE_API 的值作为代理的匹配规则。
      [process.env.VUE_APP_BASE_API]: {
        // 代理请求转发的目标地址。
        target: `http://localhost:8080`,
        // 是否改变请求的源，设置为 true 可避免跨域问题。
        changeOrigin: true,
        // 路径重写规则，将请求路径中以 VUE_APP_BASE_API 开头的部分替换为空字符串。
        pathRewrite: {
          ['^' + process.env.VUE_APP_BASE_API]: ''
        }
      }
    },
    // 禁用主机检查，可避免某些情况下的主机验证错误。
    disableHostCheck: true
  },
  // CSS 相关配置，用于设置 CSS 加载器的选项。
  css: {
    loaderOptions: {
      // Sass 加载器的配置。
      sass: {
        // 设置 Sass 编译后的输出样式为展开模式。
        sassOptions: { outputStyle: "expanded" }
      }
    }
  },
  // 直接修改 Webpack 配置的选项。
  configureWebpack: {
    // 设置 Webpack 构建项目的名称，可用于调试和输出信息。
    name: name,
    // 配置模块解析规则。
    resolve: {
      // 设置路径别名，'@' 代表项目的 src 目录，方便在代码中引用。
      alias: {
        '@': resolve('src')
      }
    },
    // 配置 Webpack 插件。
    plugins: [
      // 使用 CompressionPlugin 插件对构建后的文件进行 Gzip 压缩。
      // 参考文档：http://doc.ruoyi.vip/ruoyi-vue/other/faq.html#使用gzip解压缩静态文件
      new CompressionPlugin({
        // 不启用文件缓存，避免缓存占用磁盘空间。
        cache: false,
        // 匹配需要压缩的文件格式，这里匹配 js、css 和 html 文件。
        test: /\.(js|css|html)?$/i,
        // 压缩后的文件名格式，保持原路径和查询参数，添加 .gz 后缀。
        filename: '[path].gz[query]',
        // 使用 gzip 压缩算法。
        algorithm: 'gzip',
        // 压缩率小于 0.8 时才进行压缩，避免压缩率高的文件浪费时间。
        minRatio: 0.8
      })
    ],
  },
  // 使用链式 API 修改 Webpack 配置。
  chainWebpack(config) {
    // 删除 preload 插件，该插件用于预加载资源，删除后可能需要测试是否影响性能。
    config.plugins.delete('preload') // TODO: need test
    // 删除 prefetch 插件，该插件用于预取资源，删除后可能需要测试是否影响性能。
    config.plugins.delete('prefetch') // TODO: need test

    // 配置 svg-sprite-loader 处理 SVG 文件。
    // 排除 src/assets/icons 目录下的 SVG 文件，不使用默认的 SVG 加载器。
    config.module
      .rule('svg')
      .exclude.add(resolve('src/assets/icons'))
      .end()
    // 新增一个处理 SVG 文件的规则，只处理 src/assets/icons 目录下的 SVG 文件。
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/assets/icons'))
      .end()
      // 使用 svg-sprite-loader 加载 SVG 文件。
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      // 设置 svg-sprite-loader 的选项，定义图标的 symbolId 格式。
      .options({
        symbolId: 'icon-[name]'
      })
      .end()

    // 当环境不是开发环境时，进行以下配置。
    config
      .when(process.env.NODE_ENV !== 'development',
        config => {
          // 使用 ScriptExtHtmlWebpackPlugin 插件，将运行时代码内联到 HTML 文件中。
          config
            .plugin('ScriptExtHtmlWebpackPlugin')
            .after('html')
            .use('script-ext-html-webpack-plugin', [{
              // 匹配需要内联的运行时代码文件。
              inline: /runtime\..*\.js$/
            }])
            .end()
          // 配置代码分割，优化打包后的文件结构。
          config
            .optimization.splitChunks({
            // 对所有类型的代码块进行分割。
            chunks: 'all',
            // 缓存组配置，用于定义不同的代码分割规则。
            cacheGroups: {
              // 第三方库缓存组，将 node_modules 下的模块打包到 chunk-libs 中。
              libs: {
                name: 'chunk-libs',
                test: /[\\/]node_modules[\\/]/,
                priority: 10,
                // 只打包初始依赖的第三方模块。
                chunks: 'initial'
              },
              // Element UI 缓存组，将 Element UI 相关模块单独打包到 chunk-elementUI 中。
              elementUI: {
                name: 'chunk-elementUI', // 将 Element UI 单独打包
                priority: 20, // 优先级高于 libs 和 app，确保单独打包
                // 匹配 Element UI 相关模块，兼容 cnpm 安装的情况。
                test: /[\\/]node_modules[\\/]_?element-ui(.*)/
              },
              // 公共组件缓存组，将 src/components 目录下被引用至少 3 次的组件打包到 chunk-commons 中。
              commons: {
                name: 'chunk-commons',
                test: resolve('src/components'), // 匹配规则
                minChunks: 3, // 最小引用次数
                priority: 5,
                // 复用已存在的代码块，避免重复打包。
                reuseExistingChunk: true
              }
            }
          })
          // 将运行时代码单独打包成一个文件。
          config.optimization.runtimeChunk('single'),
            // 此处代码存在问题，{ from: ..., to: ... } 未正确集成到配置中，应是配置文件复制错误。
            // 本意可能是配置文件复制，可使用 CopyWebpackPlugin 实现。
            // 正确示例：
            // config.plugin('copy').use(CopyWebpackPlugin, [[{
            //   from: path.resolve(__dirname, './public/robots.txt'),
            //   to: './'
            // }]])
            {
              from: path.resolve(__dirname, './public/robots.txt'), // 防爬虫文件
              to: './' // 复制到根目录下
            }
        }
      )
  }
}
